import { h, toRef, reactive, unref } from 'vue';
import { DynamicInstanceConfig, IPSControl } from '@ibiz/dynamic-model-api';
import {
  IAppViewControllerBase,
  IViewEventResult,
  LogUtil,
  MobChartExpViewController,
  MobMapExpViewController,
  MobMapViewController,
  MobPickupTreeViewController,
  MobTabExpViewController,
  MobTreeExpViewController,
  Util,
  ViewTool,
} from 'ibz-core';
import { AppViewEvents } from 'ibz-core';
import {
  AppViewProps,
  MobIndexViewController,
  MobCustomViewController,
  MobEditViewController,
  MobMDViewController,
  MobPanelViewController,
  MobPickUpViewController,
  MobMPickUpViewController,
  MobCalendarViewController,
  MobPickUpMDViewController,
  MobTreeViewController,
  MobHtmlViewController,
  MobMEditViewController,
  MobChartViewController,
  MobPortalViewController,
  MobDEDashboardViewController,
  MobWFDynaEditViewController,
  MobWFDynaActionViewController,
  MobListExpViewController,
  MobOptViewController,
  MobWizardViewController,
} from 'ibz-core';
import { ComponentBase } from '../component-base';
import { AppCtrlContainer } from '../common';

/**
 * 视图组件基类
 *
 * @export
 * @class ViewComponentBase
 */
export class ViewComponentBase<Props extends AppViewProps> extends ComponentBase<Props> {
  /**
   * @description 视图是否加载完成
   * @protected
   * @type {*}
   * @memberof ViewComponentBase
   */
  protected viewIsLoaded: any;

  /**
   * @description 视图控制器
   * @protected
   * @type {IAppViewControllerBase}
   * @memberof ViewComponentBase
   */
  protected c!: IAppViewControllerBase;

  /**
   * @description 设置响应式
   * @memberof ViewComponentBase
   */
  public setup() {
    this.viewIsLoaded = toRef(this.c, 'viewIsLoaded');
    this.initReactive();
    this.emitViewEvent = this.emitViewEvent.bind(this);
    this.c.hooks.event.tap(this.emitViewEvent);
    this.initViewNavParam = this.initViewNavParam.bind(this);
    this.c.hooks.modelLoaded.tap(this.initViewNavParam);
    this.viewClose = this.viewClose.bind(this);
    this.c.hooks.closeView.tap(this.viewClose);
    this.viewMounted = this.viewMounted.bind(this);
    this.c.hooks.mounted.tap(this.viewMounted);
  }

  /**
   * @description 初始化响应式属性
   * @memberof ViewComponentBase
   */
  public initReactive() {
    this.c.ctrlRefsMap = reactive(this.c.ctrlRefsMap);
  }

  /**
   * @description 视图初始化
   * @memberof ViewComponentBase
   */
  public init() {
    this.initViewNavParam();
    this.c.viewInit().then((result: boolean) => {
      this.emitViewEvent({ viewName: this.c.viewInstance?.codeName, action: AppViewEvents.INITED, data: result });
    });
  }

  /**
   * @description 视图销毁
   * @memberof ViewComponentBase
   */
  public unmounted(): void {
    this.c.viewDestroy();
    this.c.hooks.modelLoaded.removeTap(this.initViewNavParam);
    this.c.hooks.event.removeTap(this.emitViewEvent);
    this.c.hooks.closeView.removeTap(this.viewClose);
    this.c.hooks.mounted.removeTap(this.viewMounted);
    this.emitViewEvent({ viewName: this.c.viewInstance?.codeName, action: AppViewEvents.DESTROYED, data: true });
  }

  /**
   * @description 执行视图事件
   * @param {IViewEventResult} args 事件参数
   * @memberof ViewComponentBase
   */
  public emitViewEvent(args: IViewEventResult) {
    this.ctx.emit('viewEvent', args);
  }

  /**
   * @description 视图关闭
   * @param {*} [args] 事件参数
   * @memberof ViewComponentBase
   */
  public viewClose(args?: any) {
    if (this.c.viewShowMode && Object.is(this.c.viewShowMode, 'ROUTE')) {
      this.router.back();
    } else {
      this.emitViewEvent({ viewName: this.c.viewInstance?.codeName, action: AppViewEvents.CLOSE, data: args });
    }
  }

  /**
   * @description 视图挂载完成
   * @param {*} [args] 事件参数
   * @memberof ViewComponentBase
   */
  public viewMounted(args?: any) {}

  /**
   * @description 根据视图类型获取视图控制器
   * @param {string} type 视图类型
   * @return {*}
   * @memberof ViewComponentBase
   */
  public getViewControllerByType(type: string) {
    switch (type) {
      case 'APPINDEXVIEW':
        return new MobIndexViewController(this.props);
      case 'DEMOBCUSTOMVIEW':
        return new MobCustomViewController(this.props);
      case 'DEMOBEDITVIEW':
        return new MobEditViewController(this.props);
      case 'DEMOBPANELVIEW':
        return new MobPanelViewController(this.props);
      case 'DEMOBMDVIEW':
        return new MobMDViewController(this.props);
      case 'DEMOBPICKUPVIEW':
        return new MobPickUpViewController(this.props);
      case 'DEMOBMPICKUPVIEW':
        return new MobMPickUpViewController(this.props);
      case 'DEMOBPICKUPMDVIEW':
        return new MobPickUpMDViewController(this.props);
      case 'DEMOBCALENDARVIEW':
        return new MobCalendarViewController(this.props);
      case 'DEMOBTREEVIEW':
        return new MobTreeViewController(this.props);
      case 'DEMOBCHARTVIEW':
        return new MobChartViewController(this.props);
      case 'DEMOBMAPVIEW':
        return new MobMapViewController(this.props);
      case 'DEMOBTABEXPVIEW':
        return new MobTabExpViewController(this.props);
      case 'DEMOBHTMLVIEW':
        return new MobHtmlViewController(this.props);
      case 'DEMOBPICKUPTREEVIEW':
        return new MobPickupTreeViewController(this.props);
      case 'DEMOBMEDITVIEW9':
        return new MobMEditViewController(this.props);
      case 'APPPORTALVIEW':
        return new MobPortalViewController(this.props);
      case 'DEMOBPORTALVIEW':
        return new MobDEDashboardViewController(this.props);
      case 'DEMOBWFDYNAEDITVIEW':
        return new MobWFDynaEditViewController(this.props);
      case 'DEMOBWFDYNAACTIONVIEW':
        return new MobWFDynaActionViewController(this.props);
      case 'DEMOBLISTEXPVIEW':
        return new MobListExpViewController(this.props);
      case 'DEMOBOPTVIEW':
        return new MobOptViewController(this.props);
      case 'DEMOBWIZARDVIEW':
        return new MobWizardViewController(this.props);
      case 'DEMOBCHARTEXPVIEW':
        return new MobChartExpViewController(this.props);
      case 'DEMOBTREEEXPVIEW':
        return new MobTreeExpViewController(this.props);
      case 'DEMOBMAPEXPVIEW':
        return new MobMapExpViewController(this.props);
      default:
        LogUtil.log(`暂未实现${type}类型视图`);
        return null;
    }
  }

  /**
   * @description 初始化视图导航参数
   * @param {*} [inputvalue=null] 输入值
   * @return {*}
   * @memberof ViewComponentBase
   */
  public initViewNavParam(inputvalue: any = null) {
    if (App.isPreviewMode()) {
      return;
    }
    this.c.context = {};
    this.c.viewParam = {};
    this.c.navDatas = [];
    if (this.props && this.props.navParam) {
      Object.assign(this.c.viewParam, this.props.navParam);
    }
    if (this.props && this.props.navDatas) {
      Object.assign(this.c.navDatas, this.props.navDatas);
    }
    if (App.getContext()) {
      Object.assign(this.c.context, App.getContext() ? App.getContext() : {});
    }
    if (
      this.props.viewShowMode &&
      (this.props.viewShowMode === 'MODEL' || this.props.viewShowMode === 'EMBEDDED') &&
      this.props.navContext
    ) {
      Object.assign(this.c.context, this.props.navContext);
      if (this.c.context && this.c.context.srfparentdename) {
        Object.assign(this.c.viewParam, { srfparentdename: this.c.context.srfparentdename });
      }
      if (this.c.context && this.c.context.srfparentdemapname) {
        Object.assign(this.c.viewParam, { srfparentdemapname: this.c.context.srfparentdemapname });
      }
      if (this.c.context && this.c.context.srfparentkey) {
        Object.assign(this.c.viewParam, { srfparentkey: this.c.context.srfparentkey });
      }
      if (this.c) {
        this.c.handleCustomViewData(this.c.context, this.c.viewParam);
        this.c.handleOtherViewData(this.c.context, this.c.viewParam);
      }
      return;
    }
    const path = this.route.matched[this.route.matched.length - 1].path;
    const keys: Array<any> = [];
    const curReg = this.pathToRegExp.pathToRegexp(path, keys);
    const matchArray = curReg.exec(this.route.path);
    const tempValue: Object = {};
    keys.forEach((item: any, index: number) => {
      if (matchArray[index + 1]) {
        Object.defineProperty(tempValue, item.name, {
          enumerable: true,
          value: decodeURIComponent(matchArray[index + 1]),
        });
      }
    });
    ViewTool.formatRouteParams(tempValue, this.route, this.c.context, this.c.viewParam);
    if (inputvalue && typeof inputvalue === 'string' && this.c && this.c.viewInstance?.getPSAppDataEntity()?.codeName) {
      Object.assign(this.c.context, {
        [(this.c.viewInstance?.getPSAppDataEntity()?.codeName as string).toLowerCase()]: inputvalue,
      });
    }
    if (this.c && this.c.viewInstance) {
      Object.assign(this.c.context, { srfsessionid: Util.createUUID() });
    }
    if (this.c.viewParam.srfinsttag && this.c.viewParam.srfinsttag2 && this.c && this.c.modelService) {
      const dynainstParam: DynamicInstanceConfig = this.c.modelService.getDynaInsConfig();
      Object.assign(this.c.context, { srfdynainstid: dynainstParam.id });
    }
    if (this.c.viewParam && this.c.viewParam.srfdynainstid) {
      Object.assign(this.c.context, { srfdynainstid: this.c.viewParam.srfdynainstid });
    }
    // 补充沙箱实例参数（路由）
    if (this.c.viewParam && this.c.viewParam.hasOwnProperty('srfsandboxtag')) {
      Object.assign(this.c.context, { srfsandboxtag: this.c.viewParam.srfsandboxtag });
    }
    if (this.c) {
      this.c.handleCustomViewData(this.c.context, this.c.viewParam);
      this.c.handleOtherViewData(this.c.context, this.c.viewParam);
    }
  }

  /**
   * @description 绘制视图所有部件
   * @return {*}  {*}
   * @memberof ViewComponentBase
   */
  public renderViewControls(): any {
    const controlObject: any = {};
    if (
      this.c.viewInstance &&
      this.c.viewInstance.getPSControls() &&
      (this.c.viewInstance.getPSControls() as IPSControl[]).length > 0
    ) {
      (this.c.viewInstance.getPSControls() as IPSControl[]).forEach((control: IPSControl) => {
        controlObject[control.name] = () => {
          return this.computeTargetCtrlData(control);
        };
      });
    }
    //  视图消息
    if (this.c.viewInstance.getPSAppViewMsgGroup?.()) {
      Object.assign(controlObject, {
        topMessage: () => this.renderTopMessage(),
        bodyMessage: () => this.renderBodyMessage(),
        bottomMessage: () => this.renderBottomMessage(),
      });
    }
    return controlObject;
  }

  /**
   * @description 计算目标部件所需参数
   * @param {IPSControl} controlInstance 部件模型实例
   * @return {*}
   * @memberof ViewComponentBase
   */
  public computeTargetCtrlData(controlInstance: IPSControl) {
    const targetCtrlComponent: any = App.getComponentService().getControlComponent(
      controlInstance?.controlType,
      controlInstance?.controlStyle ? controlInstance?.controlStyle : 'DEFAULT',
      controlInstance.getPSSysPFPlugin() ? `${controlInstance.getPSSysPFPlugin()?.pluginCode}` : undefined,
    );
    const targetCtrlProps = {
      controlInstance: controlInstance,
      viewState: this.c.viewState,
      viewCtx: this.c.viewCtx,
      navContext: Util.deepCopy(this.c.context),
      navParam: Util.deepCopy(this.c.viewParam),
      viewCounterServiceArray: this.c.counterServiceArray,
      enablePullDownRefresh: (this.c.viewInstance as any).enablePullDownRefresh,
      modelService: this.c.modelService,
      previewData: this.c.previewData,
      modelData: controlInstance,
      onCtrlEvent: ({ controlname, action, data }: { controlname: string; action: string; data: any }) => {
        this.c.handleCtrlEvent(controlname, action, data);
      },
    };
    this.extraCtrlParam(targetCtrlProps, controlInstance);
    //  工具栏特殊处理
    if (controlInstance.controlType == 'TOOLBAR') {
      return h(targetCtrlComponent, targetCtrlProps);
    }
    return h(AppCtrlContainer, null, {
      default: () => {
        return h(targetCtrlComponent, targetCtrlProps);
      },
    });
  }

  /**
   * @description 额外部件参数
   * @param {*} ctrlProps 部件参数
   * @param {IPSControl} controlInstance 部件模型实例
   * @memberof ViewComponentBase
   */
  public extraCtrlParam(ctrlProps: any, controlInstance: IPSControl) {}

  /**
   * @description 绘制视图顶部视图消息
   * @return {*}  {*}
   * @memberof ViewComponentBase
   */
  public renderTopMessage(): any {
    let msgDetails: any[] = [];
    if (this.c.viewMessageService) {
      msgDetails = this.c.viewMessageService.getViewMsgDetails('TOP');
    }
    if (msgDetails.length > 0) {
      return (
        <div class='view-message--top'>
          <app-mob-alert
            position='TOP'
            messageDetails={msgDetails}
            context={Util.deepCopy(this.c.context)}
            viewParam={Util.deepCopy(this.c.viewParam)}
            infoGroup={this.c.viewInstance.getPSAppViewMsgGroup()?.codeName}
            viewName={this.c.viewInstance.codeName.toLowerCase()}
          ></app-mob-alert>
        </div>
      );
    }
  }

  /**
   * @description 绘制视图内容区视图消息
   * @return {*}  {*}
   * @memberof ViewComponentBase
   */
  public renderBodyMessage(): any {
    let msgDetails: any[] = [];
    if (this.c.viewMessageService) {
      msgDetails = this.c.viewMessageService.getViewMsgDetails('BODY');
    }
    if (msgDetails.length > 0) {
      return (
        <div class='view-message--body'>
          <app-mob-alert
            position='TOP'
            messageDetails={msgDetails}
            context={Util.deepCopy(this.c.context)}
            viewParam={Util.deepCopy(this.c.viewParam)}
            infoGroup={this.c.viewInstance.getPSAppViewMsgGroup()?.codeName}
            viewName={this.c.viewInstance.codeName.toLowerCase()}
          ></app-mob-alert>
        </div>
      );
    }
  }

  /**
   * @description 绘制视图下方视图消息
   * @return {*}  {*}
   * @memberof ViewComponentBase
   */
  public renderBottomMessage(): any {
    let msgDetails: any[] = [];
    if (this.c.viewMessageService) {
      msgDetails = this.c.viewMessageService.getViewMsgDetails('BOTTOM');
    }
    if (msgDetails.length > 0) {
      return (
        <div class='view-message--bottom'>
          <app-mob-alert
            position='TOP'
            messageDetails={msgDetails}
            context={Util.deepCopy(this.c.context)}
            viewParam={Util.deepCopy(this.c.viewParam)}
            infoGroup={this.c.viewInstance.getPSAppViewMsgGroup()?.codeName}
            viewName={this.c.viewInstance.codeName.toLowerCase()}
          ></app-mob-alert>
        </div>
      );
    }
  }

  /**
   * @description 绘制视图
   * @return {*}
   * @memberof ViewComponentBase
   */
  render() {
    if (!unref(this.viewIsLoaded) || !this.c.viewInstance) {
      return null;
    }
    const targetViewLayoutComponent: string = App.getComponentService().getLayoutComponent(
      this.c.viewInstance?.viewType,
      this.c.viewInstance?.viewStyle,
    );
    return h(
      targetViewLayoutComponent,
      {
        viewInstance: this.c.viewInstance,
        navContext: this.c.context,
        navParam: this.c.viewParam,
        navDatas: this.c.navDatas,
        isShowCaptionBar: this.c.isShowCaptionBar,
        modelService: this.c.modelService,
      },
      this.renderViewControls(),
    );
  }
}
